package service

import (
    "context"

    "github.com/go-kratos/kratos/contrib/registry/consul/v2"
    "github.com/go-kratos/kratos/v2/log"
    "github.com/go-kratos/kratos/v2/transport/grpc"
    "mall/api/order/v1"
    productV1 "mall/api/product/v1"
    "mall/app/order/internal/biz"
    "mall/app/order/internal/domain"
)

// GreeterService is a greeter service.
type OrderService struct {
    v1.UnimplementedOrderServer

    uc  *biz.OrderUseCase
    log *log.Helper

    psc productV1.ProductClient
}

func NewOrderService(uc *biz.OrderUseCase, logger log.Logger, psc productV1.ProductClient) *OrderService {
    return &OrderService{
        uc:  uc,
        log: log.NewHelper(log.With(logger, "module", "service/order")),
        psc: psc,
    }
}

func NewProductClient(r *consul.Registry) productV1.ProductClient {
    conn, err := grpc.DialInsecure(
        context.Background(),
        grpc.WithEndpoint("discovery:///mall.product.service"),
        grpc.WithDiscovery(r),
    )
    if err != nil {
        panic(err)
    }
    return productV1.NewProductClient(conn)
}

func (s OrderService) Create(ctx context.Context, req *v1.OrderCreateRequest) (*v1.OrderCreateReply, error) {
    productIds := make([]uint32, 0, len(req.Products))
    productNumMap := make(map[uint32]uint, len(req.Products))
    for _, product := range req.Products {
        productIds = append(productIds, product.ProductId)
        productNumMap[product.ProductId] = uint(product.Num)
    }
    products, err := s.psc.List(ctx, &productV1.ProductListRequest{
        Ids: productIds,
    })
    if err != nil {
        return nil, err
    }

    details := make([]*domain.OrderDetail, 0, len(products.Data))
    for _, product := range products.Data {
        productNum, ok := productNumMap[product.Id]
        if !ok {
            continue
        }
        details = append(details, &domain.OrderDetail{
            ProductId:   uint(product.Id),
            ProductName: product.Name,
            UnitPrice:   float64(product.Price),
            Num:         productNum,
            Price:       float64(productNum) * float64(product.Price),
        })
    }

    if _, err := s.uc.Create(ctx, &domain.Order{Detail: details}); err != nil {
        return nil, err
    }

    return &v1.OrderCreateReply{}, nil
}

func (s OrderService) List(ctx context.Context, req *v1.OrderListRequest) (*v1.OrderListReply, error) {
    // TODO implement me
    panic("implement me")
}

func (s OrderService) Detail(ctx context.Context, req *v1.OrderDetailRequest) (*v1.OrderDetailReply, error) {
    // TODO implement me
    panic("implement me")
}
